using MediatR;
using TerritoryGame.Application.Commands;
using TerritoryGame.Domain.Entities;
using TerritoryGame.Domain.Repositories;

namespace TerritoryGame.Application.Handlers.CommandHandlers;

public class EndGameCommandHandler : IRequestHandler<EndGameCommand, EndGameResult>
{
    private readonly IGameRoomRepository _gameRoomRepository;
    private readonly IGameRepository _gameRepository;

    public EndGameCommandHandler(IGameRoomRepository gameRoomRepository, IGameRepository gameRepository)
    {
        _gameRoomRepository = gameRoomRepository;
        _gameRepository = gameRepository;
    }

    public async Task<EndGameResult> Handle(EndGameCommand request, CancellationToken cancellationToken)
    {
        try
        {
            var room = await _gameRoomRepository.GetByIdAsync(request.RoomId);
            if (room == null)
            {
                return new EndGameResult
                {
                    Success = false,
                    ErrorMessage = "Room not found"
                };
            }

            if (room.Status != GameStatus.Playing)
            {
                return new EndGameResult
                {
                    Success = false,
                    ErrorMessage = "Game is not in playing state"
                };
            }

            // End the game
            room.EndGame();
            await _gameRoomRepository.UpdateAsync(room);

            // Get game and calculate final scores
            var game = await _gameRepository.GetByRoomIdAsync(request.RoomId);
            if (game != null)
            {
                game.EndGame();
                await _gameRepository.UpdateAsync(game);
            }

            // Calculate final scores and determine winner
            var players = room.Players.Select(p => new PlayerInfo
            {
                Id = p.Id,
                NickName = p.NickName,
                Color = p.Color,
                Score = p.CurrentScore,
                Area = game?.Canvas.GetPlayerArea(p.Color) ?? 0, // 计算最终面积
                IsOnline = p.IsOnline
            }).ToList();

            // Sort players by area to determine winner
            var sortedPlayers = players.OrderByDescending(p => p.Area).ToList();
            var winner = sortedPlayers.FirstOrDefault();

            return new EndGameResult
            {
                Success = true,
                Players = players,
                Winner = winner
            };
        }
        catch (Exception ex)
        {
            return new EndGameResult
            {
                Success = false,
                ErrorMessage = ex.Message
            };
        }
    }
}
